﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ZGameFramework
{

    public class MonoBehaviourPool<T> where T : MonoBehaviour, IReference
    {
        private GameObject m_Pool;
        private T m_Template;
        private Queue<T> m_Collection;


        public T Template
        {
            get {
                if (null == m_Template)
                {
                    GameObject obj = new GameObject();
                    obj.name = string.Format( "T_{0}",  typeof(T).Name );
                    obj.AddComponent<T>();
                }

                return m_Template;
            }
            set => m_Template = value;
        }

        public GameObject Pool
        {
            get
            {
                if (null == m_Pool)
                {
                    GameObject obj = new GameObject();
                    obj.name = string.Format("T_{0}", typeof(T).Name);
                    obj.transform.SetNormalize();
                }

                return m_Pool;
            }

            set => m_Pool = value;
        }

        public Queue<T> Collection
        {
            get
            {
                if (null == m_Collection) { m_Collection = new Queue<T>(); }
                return m_Collection;
            }
            set => m_Collection = value;
        }

        /// <summary>
        /// 从引用池获取引用。
        /// </summary>
        /// <typeparam name="T">引用类型。</typeparam>
        /// <returns>引用。</returns>
        public T Acquire() 
        {

            lock (Collection)
            {
                if (Collection.Count > 0)
                {
                    T tVal = Collection.Dequeue();
                    tVal.gameObject.SetActive( true );
                    return tVal;
                }
            }

            GameObject obj = Object.Instantiate(Template.gameObject);
            T results = obj.GetComponent<T>();

            return results;
        }

        /// <summary>
        /// 归还应用
        /// </summary>
        /// <param name="t"></param>
        public void Release(T t)
        {
            if (null == t)
            {
                // todo: 抛出异常
                Debug.LogError( "t is null" );
                return;
            }

            t.Clear();
            t.transform.SetParent( Pool.transform );
            t.transform.SetNormalize();
            t.gameObject.SetActive( false );
            Collection.Enqueue( t );
        }

        /// <summary>
        /// 清空缓存池
        /// </summary>
        public void Clear()
        { }
        
    }
}